/* fastPathUtil.h - Definitions for the Fastpath utility routines   */

/* Copyright 1984-2005 Wind River Systems, Inc. */

/*
modification history
--------------------
01o,24feb05,spm  performance updates and code cleanup (SPR #100995)
01n,18jan05,vvv  osdep.h cleanup
01m,28may04,niq  Merging from base6 label POST_ITER5_FRZ16_REBASE
01l,20nov03,niq  Remove copyright_wrs.h file inclusion
01k,12nov03,rlm  Removed includes of <osdep.h> and <machdep.h>
01j,04nov03,rlm  Ran batch header path update for header re-org.
01i,12mar03,niq  Turn FF_LOG_ADDR into a function and remove the addr family
                 arg
01h,06mar03,niq  Add another logging category for fastpath monitor
01g,17feb03,deg  FF_LOG_ROUTE() changed
01f,25jan03,deg  IPADDR_ARE_SAME added
01e,23jan03,deg  IPADDR_IS_MULTICAST() added
01d,14jan03,deg  macro SIN6() added
01c,09dec02,deg  IPADDR1_ARE_SAME(), GET_ADDR_LEN_FROM_AF() added
01b,02dec02,deg  FF_ENTRY macros changed to FF_MEM macros
01a,07oct02,deg  written
*/

/*
DESCRIPTION
This file contains utility definitions for the Fastpath library, the IPv4 & IPv6 
Fast Forwarder and the Fastpath RTM monitor.
 
*/

#ifndef __INCfastPathUtil
#define __INCfastPathUtil

/* includes */

/* defines */

#define SA(p) ((struct sockaddr *)(p))
#define SIN(p) ((struct sockaddr_in *)(p))
#define SIN6(p) ((struct sockaddr_in6 *)(p))
#define SDL(p) ((struct sockaddr_dl *)(p))

#define MAYBE_OK   (OK + 1)

/* Determines if two IP addresses are same. Handles NULL arguments */
#define IPADDR1_ARE_SAME(pAddr1, pAddr2, len) \
    ((pAddr1 == pAddr2) || \
     (pAddr1 != NULL && pAddr2 != NULL && \
      (bcmp ((char *) pAddr1, (char *) pAddr2, len) == 0)))

/* This macro checks if the given IPv6 addrs are equal. Doesn't check scope */
#define IP6_ARE_ADDR_SAME(d, a)      ( \
        ((d).s6_addr32[0] == (a).s6_addr32[0]) && \
        ((d).s6_addr32[1] == (a).s6_addr32[1]) && \
        ((d).s6_addr32[2] == (a).s6_addr32[2]) && \
        ((d).s6_addr32[3] == (a).s6_addr32[3]))

/* 
 * Given two sockaddr strutures this macro checks if their IP addresses match
 * Handles NULL arguments
 */
#ifdef INET6
#define IPADDR_ARE_SAME(pAddr1, pAddr2) \
    ((pAddr1 == pAddr2) || \
     (pAddr1 != NULL && pAddr2 != NULL && \
      ((pAddr1->sa_len ==  pAddr2->sa_len) && \
       ((pAddr1->sa_family == AF_INET) ? \
        (SOCKADDR_IN(pAddr1) == SOCKADDR_IN(pAddr2)) : \
        IP6_ARE_ADDR_SAME (SA6(pAddr1), SA6(pAddr2))))))
#else
#define IPADDR_ARE_SAME(pAddr1, pAddr2) \
    ((pAddr1 == pAddr2) || \
     (pAddr1 != NULL && pAddr2 != NULL && \
      ((pAddr1->sa_len ==  pAddr2->sa_len) && \
       (SOCKADDR_IN(pAddr1) == SOCKADDR_IN(pAddr2)))))
#endif /* INET6 */

#ifdef INET6
#define IPADDR_IS_LOOPBACK(x) (((x)->sa_family == AF_INET) ? \
			       SOCKADDR_IN (x) == htonl (INADDR_LOOPBACK) : \
			       ((x)->sa_family == AF_INET6) ? \
			       IN6_IS_ADDR_LOOPBACK(&(SA6(x))) : \
                               (panic ("BAD address family: %d @ %s:%d \n", \
                                       x, __FILE__, __LINE__), 0))
#else
#define IPADDR_IS_LOOPBACK(x) (((x)->sa_family == AF_INET) ? \
                               SOCKADDR_IN (x) == htonl (INADDR_LOOPBACK) : \
			       (panic ("BAD address family: %d @ %s:%d \n", \
                                       x, __FILE__, __LINE__), 0))
#endif /* INET6 */

#ifdef INET6
#define IPADDR_IS_MULTICAST(x) (((x)->sa_family == AF_INET) ? \
			        IN_MULTICAST (SOCKADDR_IN (x)) : \
			        ((x)->sa_family == AF_INET6) ? \
			        IN6_IS_ADDR_MULTICAST(&(SA6(x))) : \
                                (panic ("BAD address family: %d @ %s:%d \n", \
                                        x, __FILE__, __LINE__), 0))
#else
#define IPADDR_IS_MULTICAST(x) (((x)->sa_family == AF_INET) ? \
                               	IN_MULTICAST (SOCKADDR_IN (x)) : \
			        (panic ("BAD address family: %d @ %s:%d \n", \
                                        x, __FILE__, __LINE__), 0))
#endif /* INET6 */

#define FF_MEM_ALLOC(size) (malloc(size))
#define FF_MEM_FREE(ref) (free((char *)(ref)))

/*
 * The Log level is a two byte value that is formed by ORing the following 2
 * bytes
 * Upper byte (MSB) :  Log path (FFL_PKT or FFL_RT)
 * Lower byte (LSB) :  logging level (FFL_INFO - FFL_PANIC)
 */

#define FFL_VERBOSE      0x1   /* Log detailed messages */
#define FFL_INFO	 0x2   /* Log informational messages */
#define FFL_WARN         0x3   /* Log warning messages */
#define FFL_ERROR	 0x4   /* Log error messages */
#define FFL_NONCRIT	 0x5   /* Log non critical messages */
#define FFL_CRIT	 0x8   /* Log critical messages */
#define FFL_PANIC	 0x9   /* Log panic messages */
#define FFL_MAX_LEVEL	 0x10  /* maximum log level */

/* Log area */

#define FFL_PKT		 0x100 /* Log messages in packet forwarding path */
#define FFL_RT		 0x200 /* Log messages in FIB management path */
#define FFL_MON		 0x400 /* Log messages in Fastpath monitor */

#ifdef DEBUG

#define FFL_LVL_MASK	 0x000000FF
#define FFL_TYPE_MASK	 0x0000FF00
#define FFL_PRINTF_MASK  0x00FF0000
#define FFL_SUSPEND_MASK 0xFF000000

#define FFL_LVL(x)	(x & FFL_LVL_MASK)
#define FFL_TYPE(x)	(x & FFL_TYPE_MASK)
#define FFL_PRINTF(x)   (x & FFL_PRINTF_MASK)
#define FFL_SUSPEND(x)  (x & FFL_SUSPEND_MASK)


#define FF_LOG_MSG0(lvl, fmt) \
        ffLogMsg(lvl, fmt, 0, 0, 0, 0, 0, 0)
#define FF_LOG_MSG1(lvl, fmt, a1) \
        ffLogMsg(lvl, fmt, (int)a1, 0, 0, 0, 0, 0)
#define FF_LOG_MSG2(lvl, fmt, a1, a2) \
        ffLogMsg(lvl, fmt, (int)a1, a2, 0, 0, 0, 0)
#define FF_LOG_MSG3(lvl, fmt, a1, a2, a3) \
        ffLogMsg(lvl, fmt, (int)a1, a2, a3, 0, 0, 0)
#define FF_LOG_MSG4(lvl, fmt, a1, a2, a3, a4) \
        ffLogMsg(lvl, fmt, (int)a1, a2, a3, a4, 0, 0)
#define FF_LOG_MSG5(lvl, fmt, a1, a2, a3, a4, a5) \
        ffLogMsg(lvl, fmt, (int)a1, a2, a3, a4, a5, 0)
#define FF_LOG_MSG6(lvl, fmt, a1, a2, a3, a4, a5, a6) \
        ffLogMsg(lvl, fmt, (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6)

/*
 * prints out the destination, netmask, gateway 
 * arguments pDstAddr, pNetmask, pGateway are from type sockaddr *
 * pDstAddr should not be NULL
 */

#define FF_LOG_ADDR	ffLogAddr

#define FF_LOG_ROUTE(lvl, pDstAddr, pRouteDstAddr, pNextHop) \
        do { \
        if (FFL_LVL (lvl) == FFL_CRIT || FFL_LVL (lvl) == FFL_PANIC || \
	    FFL_LVL (lvl) == FFL_MAX_LEVEL || \
	    ((FFL_TYPE (lvl) & FFL_TYPE (ffLibLogLevel)) && \
	     (FFL_LVL (lvl) >= FFL_LVL (ffLibLogLevel)))) \
	    { \
            ffLogRoute(pDstAddr, pRouteDstAddr, pNextHop); \
	    } \
        } while (0)
#else

#define FF_LOG_MSG0(lvl, fmt)
#define FF_LOG_MSG1(lvl, fmt, a1)
#define FF_LOG_MSG2(lvl, fmt, a1, a2)
#define FF_LOG_MSG3(lvl, fmt, a1, a2, a3)
#define FF_LOG_MSG4(lvl, fmt, a1, a2, a3, a4)
#define FF_LOG_MSG5(lvl, fmt, a1, a2, a3, a4, a5)
#define FF_LOG_MSG6(lvl, fmt, a1, a2, a3, a4, a5, a6)
#define FF_LOG_ADDR(lvl, pDstAddr, pGateway, pNetmask)                      
#define FF_LOG_ROUTE(lvl, pDstAddr, pRouteDstAddr, pNextHop)

#endif /* DEBUG */ 

/* function declarations */

#ifdef DEBUG

IMPORT VOID ffLogMsg  (ULONG lvl, unsigned char *fmt, int a1, int a2, int a3,
		       int a4, int a5, int a6);
IMPORT VOID ffLogAddr (ULONG lvl, struct sockaddr *pDstAddr, 
		       struct sockaddr *pNetmask,
		       struct sockaddr *pGateway);
IMPORT VOID ffLogRoute (struct sockaddr *pDstAddr, struct sockaddr *pRouteDstAddr,
			struct sockaddr *pNextHop);

#endif /* DEBUG */

#endif /* __INCfastPathUtil */
